package com.jiangds.open.check.checker;

import com.jiangds.open.check.Checker;
import com.jiangds.open.pattern.PatternFactory;
import java.time.LocalDate;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;

/**
 * {@link AbstractChecker} 抽象的目标
 *
 * @author jiangliang
 * @since 2021/1/5 13:48
 */
public abstract class AbstractChecker<R extends Number, T> implements Checker<R, T> {

    /**
     * 目标
     */
    private T target;

    /**
     * 目标类型
     */
    private Class<?> targetType;

    /**
     * 是否检测通过
     */
    private boolean pass;

    /**
     * 正则匹配
     */
    private Pattern pattern = null;


    private void setPass(boolean pass) {
        this.pass = pass;
    }

    public T getTarget() {
        return target;
    }

    public Class<?> getTargetType() {
        return targetType;
    }

    @Override
    public boolean isPass() {
        return pass;
    }

    AbstractChecker(T target) {
        this.target = target;
        if (isNull()) {
            targetType = null;
        } else {
            targetType = target.getClass();
        }
        this.pass = true;
    }

    Checker<R, T> notNull() {
        if (getTarget() == null) {
            this.setPass(false);
        }
        return this;
    }

    /**
     * 对象为空
     *
     * @return 是否为空
     */
    private boolean isNull() {
        return target == null;
    }

    /**
     * 判断是否需要继续校验
     * 如果[目标不为空值] 和 [之前的校验通过] 的情况下才需要继续校验
     *
     * @return 是否需要继续校验
     * true  需要继续校验
     * false 不需要继续校验,因为已经不通过了
     */
    private boolean needCheck() {
        return !isNull() && pass;
    }

    @Override
    public Checker<R, T> regex(String regex) {
        return processor(t -> {
            if (pattern == null) {
                pattern = PatternFactory.get(regex);
            }
            return pattern.matcher(t.toString()).matches();
        });
    }

    Checker<R, T> localDateRangeProcessor(Function<T, LocalDate> function, Integer min, Integer max) {
        return processor(t -> {
            LocalDate now = LocalDate.now();
                    //  今天-min天 <= 目标日期 <= 今天+max天
            return   now.plusDays(min).compareTo(function.apply(t)) <= 0
                    //当前时间 加上max天数 不晚于 target日期
                     && function.apply(t).compareTo(now.plusDays(max)) <= 0;
        });
    }

    Checker<R, T> integerRangeProcessor(Function<T, Integer> function, Integer min, Integer max) {
        return processor(t -> function.apply(t) >= min && function.apply(t) <= max);
    }

    @SuppressWarnings({"unchecked", "varargs"})
    Checker<R, T> inProcessor(BiPredicate<T, T> predicate, T... args) {
        return processor(t -> {
            for (T arg : args) {
                if (predicate.test(t, arg)) {
                    return true;
                }
            }
            return false;
        });
    }

    Checker<R, T> processor(Predicate<T> predicate) {
        if (needCheck()) {
            this.setPass(predicate.test(getTarget()));
        }
        return this;
    }

}
